import json
import time
import traceback
from typing import Union

import requests
from requests.cookies import RequestsCookieJar
from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver import ActionChains
from user_agent import generate_user_agent

from sam.util.httpUtil import get_web_driver
from sam.wrapper.CommonWrapper import logger, retry_by_special_exception


class BaseHttp(object):
    def __init__(self):
        super().__init__()
        self.user_agent = generate_user_agent()
        self.session = requests.Session()

    def get(self, url, param=None, resp_optional: str = "json", cookies: Union[dict, RequestsCookieJar] = None,
            proxies: dict = None, header: dict = None):
        if not header:
            header = {"User-Agent": self.user_agent, "Referer": url}
        if "json" == resp_optional:
            resp = requests.get(url, params=param, headers=header, cookies=cookies, proxies=proxies, verify=False)
            return json.loads(resp.text)
        else:
            return requests.get(url, params=param, headers=header, cookies=cookies, proxies=proxies, verify=False)

    def post(self, url, data=None, resp_optional: str = "json", cookies: Union[dict, RequestsCookieJar] = None,
             proxies: dict = None, header: dict = None):
        if not header:
            header = {"User-Agent": self.user_agent, "Referer": url}
        if "json" == resp_optional:
            resp = requests.post(url, json=data, headers=header, cookies=cookies, proxies=proxies, verify=False)
            return json.loads(resp.text)
        else:
            return requests.post(url, data=data, headers=header, cookies=cookies, proxies=proxies, verify=False)


class BaseBrowser(object):
    def __init__(self, headless: bool = False, images_less: bool = False):
        super().__init__()
        self.browser = get_web_driver(headless=headless, images_less=images_less)

    def click(self, css_selector):
        time.sleep(2)
        select_element = self.browser.find_element_by_css_selector(css_selector)
        self.browser.execute_script("arguments[0].click();", select_element)

    def get(self, url):
        self.browser.get(url)
        time.sleep(3)

    # @retry_by_special_exception(exception=StaleElementReferenceException)
    def move_to(self, target_element, max_retry_times=3):
        attempts = 1
        while attempts <= max_retry_times:
            try:
                # 滑动滚动条到某个指定的元素 将下拉滑动条滑动到当前div区域
                self.browser.execute_script("arguments[0].scrollIntoView();", target_element)
                # 然后将鼠标也移动到这个位置
                ActionChains(self.browser).move_to_element(target_element).perform()
                time.sleep(3)
                break
            except StaleElementReferenceException as e:
                logger.error(traceback.print_exc())
                logger.info(f" 发生指定异常: {e} , 将进行第 {attempts} 次 尝试")
                attempts += 1
        else:
            logger.info(f" 发生指定异常: {StaleElementReferenceException} , 在 {max_retry_times} 次 尝试失败后 退出尝试")

    @retry_by_special_exception(exception=StaleElementReferenceException)
    def move_to2(self, target_element):
        # 滑动滚动条到某个指定的元素 将下拉滑动条滑动到当前div区域
        self.browser.execute_script("arguments[0].scrollIntoView();", target_element)
        # 然后将鼠标也移动到这个位置
        ActionChains(self.browser).move_to_element(target_element).perform()
        time.sleep(3)

    @retry_by_special_exception(exception=StaleElementReferenceException)
    def click_on(self, target_element):
        self.browser.execute_script("arguments[0].scrollIntoView();", target_element)
        ActionChains(self.browser).move_to_element(target_element).click().perform()
        time.sleep(3)

    def __del__(self):
        if self.browser:
            self.browser.quit()
            print("无图浏览器退出")


def test3():
    pass


if __name__ == '__main__':
    test3()
    print('end')
